<?php
namespace App\Http\Controllers\Api\Buz;

use App\Http\Controllers\Controller;
use App\Lib\BCMathLib;
use App\Models\DictPayment;
use App\Models\PlatUser;
use App\Models\RechargeOrder;
use App\Repositories\Criteria\AuthUserCriteria;
use App\Repositories\Criteria\MchInfoFilterCriteria;
use App\Repositories\Criteria\MchNoCriteria;
use App\Repositories\Criteria\OrderStatusCriteria;
use App\Repositories\Criteria\PmSelectCriteria;
use App\Repositories\Criteria\TimeFilterCriteria;
use App\Repositories\Eloquent\PlatUserRepositoryEloquent;
use App\Repositories\Eloquent\RechargeOrderRepositoryEloquent;
use App\Services\ApiResponseService;
use App\Services\PlatUserService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class StatisticController extends Controller
{
    public $orderRepo;

    public function __construct(RechargeOrderRepositoryEloquent $rechargeOrderRepositoryEloquent)
    {
        $this->orderRepo = $rechargeOrderRepositoryEloquent;
    }

    public function payments(Request $request, BCMathLib $mathLib)
    {
        $pm_id = 0;
        if (($pm = $request->input('payment', 'all')) != 'all') {
            $pm_id = DictPayment::recharge()->where('identify', $pm)->firstOrFail();
            $pm_id = $pm_id->id;
        }
        $this->orderRepo->pushCriteria(new AuthUserCriteria());
        $this->orderRepo->pushCriteria(new TimeFilterCriteria($request));
        $this->orderRepo->pushCriteria(new PmSelectCriteria($pm_id));

        $payments = DictPayment::recharge()->get()->pluck('name', 'id');
        $orders = $this->orderRepo->get(['pm_id', 'order_amt', 'order_status', 'order_settle', 'proxy', 'proxy_settle']);
        $total_orders = $orders->count();
        $total_amt = $mathLib->convertDecimal($orders->sum('order_amt'));
        $done_orders = $orders->where('order_status', 1)->count();
        $done_amt = $mathLib->convertDecimal($orders->where('order_status', 1)->sum('order_amt'));
        $total_income = $mathLib->convertDecimal($orders->where('order_status', 1)->sum('order_settle'));
        $pmStatistic = [];
        foreach ($orders->chunk(200) as $order) {
            $pmOrders = $order->groupBy('pm_id');
            foreach ($pmOrders as $pm => $pOrders) {
                @$pmStatistic[$pm]['t_orders'] += $pOrders->count();
                @$pmStatistic[$pm]['t_amt'] = bcadd($pmStatistic[$pm]['t_amt'], $mathLib->convertDecimal($pOrders->sum('order_amt')), 2);
                $pOrders = $pOrders->where('order_status', 1);
                @$pmStatistic[$pm]['d_orders'] += $pOrders->count();
                @$pmStatistic[$pm]['d_amt'] = bcadd($pmStatistic[$pm]['d_amt'], $mathLib->convertDecimal($pOrders->sum('order_amt')), 2);
                @$pmStatistic[$pm]['income'] = bcadd($pmStatistic[$pm]['income'], $mathLib->convertDecimal($pOrders->sum('order_settle')), 6);
            }
        }
        $returnData = [];
        foreach ($payments as $k => $payment) {
            if ( ! array_key_exists($k, $pmStatistic)) {
                $singleData = [
                    'p_name' => $payment,
                    't_orders' => 0,
                    't_amt' => 0,
                    'd_orders' => 0,
                    'd_amt' => 0,
                    'income' => 0
                ];
            } else {
                $singleData = [
                   'p_name' => $payment
                ] + $pmStatistic[$k];
            }
            $returnData[] = $singleData;
        }
        array_push($returnData, [
            'p_name' => '总计',
            't_orders' => $total_orders,
            'd_orders' => $done_orders,
            't_amt' => $total_amt,
            'd_amt' => $done_amt,
            'income' => $total_income
        ]);
        return ApiResponseService::returnData($returnData);
    }

    public function subMchOrders(Request $request)
    {
        $payment = $request->input('payment') ? : 'all';
        $order_status = $request->input('order_status') ? : 99;
        $mch_no = $request->input('merchant_no') ?? '';
        $mch_code = $request->input('mch_code', null);
        $pageSize = $request->input('pageSize') ?? 20;
        $pm_id = 0;
        if (($pm = $request->input('payment', 'all')) != 'all') {
            $pm_id = DictPayment::recharge()->where('identify', $pm)->firstOrFail();
            $pm_id = $pm_id->id;
        }
        $this->orderRepo->pushCriteria(new PmSelectCriteria($pm_id));
        $this->orderRepo->pushCriteria(new MchInfoFilterCriteria($mch_code, ['code'], false));
        $this->orderRepo->pushCriteria(new AuthUserCriteria('proxy'));
        $this->orderRepo->pushCriteria(new TimeFilterCriteria($request));
        $this->orderRepo->pushCriteria(new OrderStatusCriteria($order_status, 'order_status'));
        $this->orderRepo->pushCriteria(new MchNoCriteria($mch_no));
        $orders = $this->orderRepo
            ->orderBy('created_at', 'desc')
            ->with(['payment' => function ($query) use ($payment){
                $query->select('id', 'identify', 'name');
            }, 'platuser' => function ($query) {
                $query->select('id', 'code');
            }]);
        $total = clone $orders;
        $total = $total->get();
        $orders = $orders->paginate($pageSize, ['plat_no', 'uid', 'merchant_no', 'order_amt', 'order_settle', 'proxy', 'proxy_settle', 'order_status', 'pm_id', 'created_at']);

        $page_total_amt = $total->sum('order_amt');
        $total = $total->where('order_status', 1);
        $page_done_amt = $total->sum('order_amt');
        $total_income = 0;
        foreach ($total->chunk(200) as $tOrders) {
            $tOrders->each(function ($item, $value) use (&$total_income){
                $diff = bcsub($item->proxy_settle, $item->order_settle, 6);
                if (bccomp($diff, 0, 6) == 1) {
                    $total_income = bcadd($total_income, $diff, 6);
                }
            });
        }

        $page_total_amt = number_format($page_total_amt, 2, '.', '');
        $page_done_amt = number_format($page_done_amt, 2, '.', '');
        $page_total_income = $total_income;

        $items = $orders->items();
        foreach ($items as &$item) {
            $diff = bcsub($item->proxy_settle, $item->order_settle, 6);
            $item->order_income = $item->order_status == 1
                ? (bccomp($diff, 0, 6) == 1
                    ? $diff
                    : 0)
                : '-';
        }
        return ApiResponseService::returnData($orders->toArray() + compact('page_total_amt', 'page_done_amt', 'page_total_income'));

    }

    public function subStatistic(Request $request, BCMathLib $mathLib)
    {
        $pm_id = 0;
        if (($pm = $request->input('payment', 'all')) != 'all') {
            $pm_id = DictPayment::recharge()->where('identify', $pm)->firstOrFail();
            $pm_id = $pm_id->id;
        }
        $mch_code = $request->input('mch_code', null);
        $this->orderRepo->pushCriteria(new AuthUserCriteria('proxy'));
        $this->orderRepo->pushCriteria(new TimeFilterCriteria($request));
        $this->orderRepo->pushCriteria(new PmSelectCriteria($pm_id));
        $this->orderRepo->pushCriteria(new MchInfoFilterCriteria($mch_code, ['code'], false));

        $payments = DictPayment::recharge()->get()->pluck('name', 'id');
        $orders = $this->orderRepo->get(['pm_id', 'order_amt', 'order_status', 'order_settle', 'proxy', 'proxy_settle']);
        $total_orders = $orders->count();
        $total_amt = $mathLib->convertDecimal($orders->sum('order_amt'));
        $done_orders = $orders->where('order_status', 1)->count();
        $done_amt = $mathLib->convertDecimal($orders->where('order_status', 1)->sum('order_amt'));
        $total_income = 0;
        foreach ($orders->where('order_status', 1)->chunk(2000) as $order) {
            $order->each(function ($item, $value) use ( & $total_income){
                $diff = bcsub($item->proxy_settle, $item->order_settle, 6);
                if (bccomp($diff, 0, 6) == 1) {
                    $total_income = bcadd($total_income, $diff, 6);
                }
            });
        }
        $pmStatistic = [];
        foreach ($orders->chunk(200) as $order) {
            $pmOrders = $order->groupBy('pm_id');
            foreach ($pmOrders as $pm => $pOrders) {
                @$pmStatistic[$pm]['t_orders'] += $pOrders->count();
                @$pmStatistic[$pm]['t_amt'] = bcadd($pmStatistic[$pm]['t_amt'], $mathLib->convertDecimal($pOrders->sum('order_amt')), 2);
                $pOrders = $pOrders->where('order_status', 1);
                @$pmStatistic[$pm]['d_orders'] += $pOrders->count();
                @$pmStatistic[$pm]['d_amt'] = bcadd($pmStatistic[$pm]['d_amt'], $mathLib->convertDecimal($pOrders->sum('order_amt')), 2);
                $ptIncome = 0;
                $pOrders->each(function ($item, $value) use ( & $ptIncome){
                    $diff = bcsub($item->proxy_settle, $item->order_settle, 6);
                    if (bccomp($diff, 0, 6) == 1) {
                        $ptIncome = bcadd($ptIncome, $diff, 6);
                    }
                });
                @$pmStatistic[$pm]['income'] = bcadd($pmStatistic[$pm]['income'], $ptIncome, 6);
            }
        }
        $returnData = [];
        foreach ($payments as $k => $payment) {
            if ( ! array_key_exists($k, $pmStatistic)) {
                $singleData = [
                    'p_name' => $payment,
                    't_orders' => 0,
                    't_amt' => 0,
                    'd_orders' => 0,
                    'd_amt' => 0,
                    'income' => 0
                ];
            } else {
                $singleData = [
                        'p_name' => $payment
                    ] + $pmStatistic[$k];
            }
            $returnData[] = $singleData;
        }
        array_push($returnData, [
            'p_name' => '总计',
            't_orders' => $total_orders,
            'd_orders' => $done_orders,
            't_amt' => $total_amt,
            'd_amt' => $done_amt,
            'income' => $total_income
        ]);
        return ApiResponseService::returnData($returnData);
    }


    public function subMchStatistic(Request $request,
                                    PlatUserRepositoryEloquent $userRepository,
                                    BCMathLib $mathLib)
    {
        $pm_id = 0;
        if (($pm = $request->input('payment', 'all')) != 'all') {
            $pm_id = DictPayment::recharge()->where('identify', $pm)->first();
            $pm_id = $pm_id ? $pm_id->id : 0;
        }
        $pageSize = $request->input('pageSize') ?? 20;
        $mch_code = $request->input('mch_code', null);
        $userRepository->pushCriteria(new AuthUserCriteria('upper_id'));
        $userRepository->pushCriteria(new MchInfoFilterCriteria($mch_code, ['code'], false));
        $subUsers = $userRepository->with(['orders' => function ($query) use ($request, $pm_id) {
            $start_at = $request->input('start_at')? : null;
            $end_at = $request->input('end_at') ? $request->input('end_at').':59': null;
            if ( ! is_null($start_at)) {
                $query = $query->where('created_at', '>=', $start_at);
            }
            if (! is_null($end_at)) {
                $query = $query->where('created_at', '<=', $end_at);
            }
            $query = $query->where('proxy', Auth::id());
            if ($pm_id != 0) {
                $query = $query->where('pm_id', '=', $pm_id);
            }
            return $query->select('uid', 'pm_id', 'order_amt', 'order_status', 'order_settle', 'proxy', 'proxy_settle');
        }])->paginate($pageSize, ['id', 'upper_id', 'code']);
        $returnData = [];
        $items = $subUsers->items();
        foreach ($items as $item) {
            $orders = $item->orders;
            $singleMch[$item->id] = [];
            foreach ($orders->chunk(200) as $order) {
                @$singleMch[$item->id]['t_orders'] += $order->count();
                @$singleMch[$item->id]['t_amt'] = bcadd($singleMch[$item->id]['t_amt'], $mathLib->convertDecimal($order->sum('order_amt')), 2);
                $order = $order->where('order_status', 1);
                @$singleMch[$item->id]['d_orders'] += $order->count();
                @$singleMch[$item->id]['d_amt'] = bcadd($singleMch[$item->id]['d_amt'], $mathLib->convertDecimal($order->sum('order_amt')), 2);
                $ptIncome = 0;
                $order->each(function ($item, $value) use ( & $ptIncome){
                    $diff = bcsub($item->proxy_settle, $item->order_settle, 6);
                    if (bccomp($diff, 0, 6) == 1) {
                        $ptIncome = bcadd($ptIncome, $diff, 6);
                    }
                });
                @$singleMch[$item->id]['income'] = bcadd($singleMch[$item->id]['income'], $ptIncome, 6);
            }
            $returnData[] = [
                'mch_code' => $item->code
            ] + $singleMch[$item->id];
        }
        $subUsers = $subUsers->toArray();
        $subUsers['data'] = $returnData;
        return ApiResponseService::returnData($subUsers);

    }
}
